# _*_ coding: utf-8 _*_
from odoo import models, api, fields, _, SUPERUSER_ID
import odoo.addons.decimal_precision as dp
from odoo.exceptions import ValidationError


class PurchaseRequestOrder(models.Model):
    _inherit = ["order.priority.mixin", "stock.view.quant.mixin"]
    _name = "purchase.request.order"
    _order = 'sequence, id desc'

    READONLY_STATES = {
        'purchase_requesting': [('readonly', True)],
        'price_comparing': [('readonly', True)],
        'allow_purchase': [('readonly', True)],
        'close': [('readonly', True)],
        'cancel': [('readonly', True)],
    }

    name = fields.Char('Order Reference', required=True, index=True, copy=False, default='New')
    date = fields.Date(string="Date", default=lambda self: fields.Date.today(), states=READONLY_STATES)
    data_planned = fields.Date(string="Scheduled Date", default=lambda self: fields.Date.today())
    supplier_id = fields.Many2one("res.partner", string="Supplier", required=True, states=READONLY_STATES)
    currency_id = fields.Many2one('res.currency', 'Currency', required=True, states=READONLY_STATES,
                                  default=lambda self: self.env.user.company_id.currency_id.id)
    line_ids = fields.One2many("purchase.request.order.line", "order_id", states=READONLY_STATES,
                               copy=True)

    amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True, readonly=True, compute='_amount_all',
                                     track_visibility='always')
    amount_tax = fields.Monetary(string='Taxes', store=True, readonly=True, compute='_amount_all')
    amount_total = fields.Monetary(string='Total', store=True, readonly=True, compute='_amount_all')

    default_currency_id = fields.Many2one("res.currency", default=lambda self: self.env.user.company_id.currency_id,
                                          readonly=True)
    amount_untaxed_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_amount_all',
                                                      string='Untaxed Amount Default Currency', store=True)
    amount_tax_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_amount_all',
                                                  string='Taxes Default Currency', store=True)
    amount_total_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_amount_all',
                                                    string='Total Default Currency', store=True)

    department_id = fields.Many2one("hr.department", string="Department", states=READONLY_STATES)
    user_id = fields.Many2one("res.users", string="User", default=lambda self: self.env.user, states=READONLY_STATES)
    note = fields.Text(string="Note")
    company_id = fields.Many2one('res.company', 'Company', required=True, index=True, states=READONLY_STATES,
                                 default=lambda self: self.env.user.company_id.id)
    fiscal_position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position')
    payment_term_id = fields.Many2one('account.payment.term', 'Payment Terms')

    state = fields.Selection([
        ('draft', 'Draft'),
        ("purchase_requesting", "Purchase Requesting"),
        ("price_comparing", "Price Comparing"),
        ("allow_purchase", "Allow Purchase"),
        ("close", "Close"),
        ("cancel", "Cancel"),
    ], string="State", default="draft", copy=False)

    @api.depends('line_ids.price_total')
    def _amount_all(self):
        for order in self:
            amount_untaxed = amount_tax = 0.0
            for line in order.line_ids:
                amount_untaxed += line.price_subtotal
                # FORWARDPORT UP TO 10.0
                if order.company_id.tax_calculation_rounding_method == 'round_globally':
                    taxes = line.taxes_id.compute_all(line.price_unit, line.order_id.currency_id, line.product_qty, product=line.product_id, partner=line.order_id.partner_id)
                    amount_tax += sum(t.get('amount', 0.0) for t in taxes.get('taxes', []))
                else:
                    amount_tax += line.price_tax
            order.update({
                'amount_untaxed': order.currency_id.round(amount_untaxed),
                'amount_tax': order.currency_id.round(amount_tax),
                'amount_total': amount_untaxed + amount_tax,
            })
            default_currency = self.default_currency_id
            order.update({
                "amount_untaxed_default_currency": order.currency_id.compute(order["amount_untaxed"], default_currency),
                "amount_tax_default_currency": order.currency_id.compute(order["amount_tax"], default_currency),
                "amount_total_default_currency": order.currency_id.compute(order["amount_total"], default_currency),
            })

    @api.model
    def create(self, vals):
        if vals.get('name', 'New') == 'New':
            vals['name'] = self.env['ir.sequence'].next_by_code('purchase.request.order') or '/'
        return super(PurchaseRequestOrder, self).create(vals)

    def action_confirm(self):
        for order in self:
            for line in order.line_ids:
                if not line.delivery_date:
                    raise ValidationError(_("Delivery Date not set in line."))
        self.write({
            "state": "purchase_requesting"
        })
        self.line_ids.write({
            "state": "purchase_requesting"
        })

    def action_approve(self):
        self.write({
            "state": "price_comparing"
        })
        self.line_ids.write({
            "state": "price_comparing"
        })

    def action_allow_purchase(self):
        self.write({
            "state": "allow_purchase"
        })
        self.line_ids.write({
            "state": "allow_purchase"
        })

    def action_cancel(self):
        self.write({
            "state": "cancel"
        })
        self.line_ids.write({
            "state": "cancel"
        })

    def action_close(self):
        self.write({
            "state": "close"
        })
        self.line_ids.write({
            "state": "close"
        })

    def action_create_purchase_order(self):
        self.ensure_one()
        order = self
        PurchaseOrder = self.env["purchase.order"]
        purchase_order = PurchaseOrder.search([
            ("partner_id", "=", order.supplier_id.id),
            ("user_id", "=", order.user_id.id),
            ("state", "=", "draft")
        ])
        lines = order.line_ids.filtered(lambda line: line.state == "allow_purchase")

        if not lines:
            raise ValidationError(_("There is no allow purchase line."))

        line_vals = [(0, 0, {
            "name": l.product_id.name,
            "product_id": l.product_id.id,
            "product_uom": l.product_uom_id.id,
            "date_planned": l.delivery_date,
            "product_qty": l.product_qty,
            "price_unit": l.price_unit,
            "note": l.note,
            "request_order_line_id": l.id
        }) for l in lines]
        if purchase_order:
            vals = {
                "order_line": line_vals
            }
            purchase_order.write(vals)
        else:
            vals = {
                "partner_id": order.supplier_id.id,
                "user_id": order.user_id.id,
                "order_line": line_vals
            }
            purchase_order = PurchaseOrder.create(vals)
        lines.write({
            "state": "already_purchase"
        })
        if purchase_order.origin and order.name not in purchase_order.origin:
            purchase_order.origin += "," + order.name
        else:
            purchase_order.origin = order.name

        return {
            'type': 'ir.actions.act_window',
            'res_model': purchase_order._name,
            'res_id': purchase_order.id,
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'current'
        }

    @api.multi
    def action_view_quants(self):
        self.ensure_one()
        products = self.line_ids.mapped("product_id")
        return self.action_view_quant_by_product_ids(products.ids)


class PurchaseRequestOrderLine(models.Model):
    _name = "purchase.request.order.line"

    order_id = fields.Many2one("purchase.request.order", string="Request Order")
    supplier_id = fields.Many2one("res.partner", related="order_id.supplier_id", string="Supplier")
    requisition_line_id = fields.Many2one("purchase.requisition.line",
                                          string="purchase Requisition Line")
    product_id = fields.Many2one("product.product", string="Product")
    product_uom_id = fields.Many2one("product.uom", string="UOM")
    product_qty = fields.Float(string="Product Quantity")
    delivery_date = fields.Date(string="Delivery Date", required=True)
    price_unit = fields.Float(string='Unit Price', required=True, digits=dp.get_precision('Product Price'))
    currency_id = fields.Many2one(related='order_id.currency_id', store=True, string='Currency', readonly=True)
    taxes_id = fields.Many2many('account.tax', string='Taxes',
                                domain=['|', ('active', '=', False), ('active', '=', True)])

    price_subtotal = fields.Monetary(compute='_compute_amount', string='Subtotal', store=True)
    price_total = fields.Monetary(compute='_compute_amount', string='Total', store=True)
    price_tax = fields.Monetary(compute='_compute_amount', string='Tax', store=True)

    default_currency_id = fields.Many2one("res.currency", default=lambda self: self.env.user.company_id.currency_id,
                                          readonly=True)
    price_unit_default_currency = fields.Float(string='Unit Price Default Currency', required=True,
                                               digits=dp.get_precision('Product Price'),
                                               compute='_compute_amount')
    price_subtotal_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_compute_amount',
                                                      string='Subtotal Default Currency', store=True)
    price_total_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_compute_amount',
                                                   string='Total Default Currency', store=True)
    price_tax_default_currency = fields.Monetary(currency_field="default_currency_id", compute='_compute_amount',
                                                 string='Tax Default Currency', store=True)

    note = fields.Text(string="Note")
    department_id = fields.Many2one("hr.department", string="Department")
    user_id = fields.Many2one("res.users", string="User")
    state = fields.Selection([
        ('draft', 'Draft'),
        ("purchase_requesting", "Purchase Requesting"),
        ("price_comparing", "Price Comparing"),
        ("allow_purchase", "Allow Purchase"),
        ("already_purchase", "Already Purchase"),
        ("close", "Close"),
        ("cancel", "Cancel"),
    ], string="State", default="draft", readonly=True)

    @api.onchange("product_id")
    def _onchange_product_id(self):
        self.ensure_one()
        res = {}

        self.product_uom_id = self.product_id.uom_id
        fpos = self.order_id.fiscal_position_id
        if self.env.uid == SUPERUSER_ID:
            company_id = self.env.user.company_id.id
            self.taxes_id = fpos.map_tax(self.product_id.supplier_taxes_id.filtered(lambda r: r.company_id.id == company_id))
        else:
            self.taxes_id = fpos.map_tax(self.product_id.supplier_taxes_id)

        return res

    @api.depends('product_qty', 'price_unit', 'taxes_id', "currency_id")
    def _compute_amount(self):
        default_currency = self.env.user.company_id.currency_id
        for line in self:
            taxes = line.taxes_id.compute_all(line.price_unit, line.order_id.currency_id, line.product_qty,
                                              product=line.product_id, partner=line.order_id.supplier_id)
            line.update({
                'price_tax': taxes['total_included'] - taxes['total_excluded'],
                'price_total': taxes['total_included'],
                'price_subtotal': taxes['total_excluded'],
            })

            line.update({
                "price_unit_default_currency": line.currency_id.compute(line["price_unit"], default_currency),
                "price_tax_default_currency": line.currency_id.compute(line["price_tax"], default_currency),
                "price_total_default_currency": line.currency_id.compute(line["price_total"], default_currency),
                "price_subtotal_default_currency": line.currency_id.compute(line["price_subtotal"], default_currency)
            })

    def action_allow_purchase(self):
        self.write({
            "state": "allow_purchase"
        })
        for line in self:
            line.order_id.write({
                "state": "allow_purchase"
            })

    def action_cancel(self):
        self.write({
            "state": "cancel"
        })
